#!/bin/ash

. /etc/initrd.defaults

backup() {
	echo -ne "\033[0G\033[0K"
}

strlen() {
	if [ -z "$1" ]
	then
		echo "usage: strlen <variable_name>"
		die
	fi
	eval echo "\${#${1}}"
}

parse_opt() {
	case "$1" in
		*\=*)
			local key_name="`echo "$1" | cut -f1 -d=`"
			local key_len=`strlen key_name`
			local value_start=$((key_len+2))
			echo "$1" | cut -c ${value_start}-
		;;
	esac
}

modules_load() {
	for module in $*
	do
		echo ${module} >> /etc/modules/extra_load
	done

	modules_scan extra_load
}

modules_scan() {
	local MODS
	[ -d /etc/modules/${1} ] || touch /etc/modules/${1}

	[ -f /etc/modules/${1} ] && MODS=`cat /etc/modules/${1}`
	for x in ${MODS}
	do
		MLOAD=`echo ${MLIST} | sed -e "s/.*${x}.*/${x}/"`
		if [ "${MLOAD}" = "${x}" ] # Only module to no-load
		then
			echo -e "${BOLD}   ::${NORMAL} Skipping ${x}..."
		elif [ "${MLOAD}" = "${MLIST}" ] # == No change == No specified no-load
		then
			[ -n "${DEBUG}" ] && echo -ne "${BOLD}   ::${NORMAL} Checking for ${x}..."
			# find -name does not work since the return status is always zero
			if find /lib/modules | grep /"${x}${KSUFF}" >/dev/null 2>&1
			then
				echo -ne "${BOLD}   ::${NORMAL} Scanning for ${x}..."
				modprobe ${x} -n
				backup
				echo -ne "${NORMAL}"
			fi
		else
			echo -e "${BOLD}   ::${NORMAL} Skipping ${x}..."
		fi
	done
}

findcdmount() {
	if [ "$#" -gt "0" ]
	then
		for x in $*
		do
			# Check for a block device to mount
			if [ -b "${x}" ]
			then
				good_msg "Attempting to mount media:- ${x}"
				if [ -z "${CDROOT_DEV}" ]
				then
					mount -t auto ${x} ${NEW_ROOT}/mnt/cdrom \
						> /dev/null 2>&1
				else
					mount -t iso9660 ${x} ${NEW_ROOT}/mnt/cdrom \
						> /dev/null 2>&1
				fi
				if [ "$?" = '0' ]
				then
					# Check for a LiveCD
					if [ -f ${NEW_ROOT}/mnt/cdrom/${SUBDIR}/livecd ]
					then
						REAL_ROOT="${x}"
						break
					else
						umount ${NEW_ROOT}/mnt/cdrom
					fi
				fi
			fi
		done
		if [ "${REAL_ROOT}" != '' ]
		then
			good_msg "Media found on ${x}"
		fi
	fi
}

findkeymount() {
        if [ "$#" -gt "0" ]
        then
                for x in $*
                do
                        # Check for a block device to mount
                        if [ -b "${x}" ]
                        then
				if [ ${crypt_silent} = '' ]
				then
	                                good_msg "Attempting to mount key media:- ${x}"
				fi

                                mount -r -t auto ${x} ${NEW_ROOT}/mnt/keydev \
                                                > /dev/null 2>&1
                                if [ "$?" = '0' ]
                                then
                                        # Check for the key
                                        if [ -e ${NEW_ROOT}/mnt/keydev/${LUKS_ROOT_KEY} ]
                                        then
                                                LUKS_ROOT_KEYDEV="${x}"
						umount ${NEW_ROOT}/mnt/keydev
                                                break
                                        else
                                                umount ${NEW_ROOT}/mnt/keydev
                                        fi
                                fi
                        fi
                done
                if [ "${LUKS_ROOT_KEYDEV}" != '' ]
                then
			if [ ${crypt_silent} = '' ]
			then
	                        good_msg "Key media found on ${x}"
			fi
                fi
        fi
}


cache_cd_contents() {
	# Check loop file exists and cache to ramdisk if DO_cache is enabled
	if [ "${LOOPTYPE}" != "noloop" ] && [ "${LOOPTYPE}" != "sgimips" ]
	then
		check_loop
		if [ "${DO_cache}" ]
		then
			# TODO: Check the size of the image versus the size of our tmpfs
			# along with the amount of available RAM and increase tmpfs size
			# if necessary. (Not having awk sucks...)
			# z=0
			# for i in $(cat /proc/meminfo | grep -e ^MemFree -e ^Cached | \
			# cut -d: -f2 | cut -dk -f1 | sed -e "s/^\s*//") ; do
			# z=$(($z + $i)) ; done
			# echo $z
			good_msg "Copying loop file for caching..."
			cp -a ${NEW_ROOT}/mnt/cdrom/${LOOP} ${NEW_ROOT}/mnt/${LOOP}
			if [ $? -ne 0 ]
			then
				bad_msg "Failed to cache the loop file! Lack of space?"
				rm -rf ${NEW_ROOT}/mnt/livecd.* 2>/dev/null
				rm -rf ${NEW_ROOT}/mnt/zisofs 2>/dev/null
			else
				LOOPEXT='../'
			fi
		fi
	fi
}

mount_sysfs() {
	if [ "${KV_2_6_OR_GREATER}" ]
	then
		# Udev is semi-broken on non /sys sysfs mount points.
		mount -t sysfs /sys /sys >/dev/null 2>&1
		ret=$?
	
		# sysfs mount failed .. udev wont work fall back to devfs if available
		[ "$ret" -eq '0' ] || USE_UDEV_NORMAL=0
	fi
}

# Insert a directory tree $2 to an union specified by $1
# Top-level read-write branch is specified by it's index 0
# $1 = union absolute path (starting with /)
# $2 = path to data directory
#
union_insert_dir() {
	# Always mount it over the precedent (add:1:)
	mount -n -o remount,add:1:$2=rr aufs $1
	if [ $? = '0' ]
	then
		good_msg "Addition of $2 to $1 successful"
	fi
}

# Insert all modules found in $1, usually mnt/cdrom
# added to allow users to add their own apps.
union_insert_modules() {
	for module in `ls ${NEW_ROOT}/$1/modules/*.mo | sort`
	do
		mkdir -p ${MEMORY}/modules/`basename ${module} .mo`
		mount -o loop,ro ${module} ${MEMORY}/modules/`basename ${module} .mo`
		union_insert_dir $UNION ${MEMORY}/modules/`basename ${module} .mo`
	done
}


findnfsmount() {

	if [ "${IP}" != '' ] || busybox udhcpc -R rootpath -n -s /bin/udhcpc.scripts
	then
		[ -e /rootpath ] && NFSROOT=`cat /rootpath`

		if [ "${NFSROOT}" = '' ]
		then
			# Obtain NFSIP	
			OPTIONS=`busybox dmesg | grep rootserver | sed -e "s/,/ /g"`
			for OPTION in $OPTIONS
			do
				if [ `echo $OPTION | sed -e "s/=/ /g" | cut -d " " -f 1` = 'rootserver' ]
				then
					NFSIP=`echo $OPTION | sed -e "s/=/ /g" | cut -d " " -f 2`
				fi 
			done
			
			# Obtain NFSPATH
			OPTIONS=`busybox dmesg | grep rootpath | sed -e "s/,/ /g"`	
			for OPTION in $OPTIONS
			do
				if [ `echo $OPTION | sed -e "s/=/ /g" | cut -d " " -f 1` = 'rootpath' ]
				then
					NFSPATH=`echo $OPTION | sed -e "s/=/ /g" | cut -d " " -f 2`
		 		fi
			done

			# Setup NFSROOT
			if [ "${NFSIP}" != '' ] && [ "$NFSPATH" != '' ]
			then
				NFSROOT="${NFSIP}:${NFSPATH}"
			else
				bad_msg "The DHCP Server did not send a valid root-path."
				bad_msg "Please check your DHCP setup, or provide a nfsroot=<...> parameter."
			fi
		fi

		if [ "${NFSROOT}" != '' ]
		then
			if [ "${CDROOT}" != '0' ]
			then
				good_msg "Attempting to mount NFS CD image on ${NFSROOT}"
				mount -t nfs -o ro,nolock,rsize=1024,wsize=1024 ${NFSROOT} ${NEW_ROOT}/mnt/cdrom
				if [ "$?" = '0' ]
				then
					REAL_ROOT="/dev/nfs"
				else
					bad_msg "NFS Mounting failed. Is the path corrent ?"
				fi
			else	
				good_msg "Attemping to mount NFS root on ${NFSROOT}"
				mount -t nfs -o ro,nolock,rsize=1024,wsize=1024 ${NFSROOT} ${NEW_ROOT}
				if [ "$?" = '0' ]
				then
					REAL_ROOT="/dev/nfs"
				else
					bad_msg "NFS Mounting failed. Is the path correct ?"
				fi
				# FIXME: Need to start portmap and the other rpc daemons in order to
				# FIXME: remount rw.
			fi

		fi
	fi
}

kill_devfsd() {
	killall devfsd > /dev/null 2>&1
}

check_loop() {
	if [ "${LOOP}" = '' -o ! -e "mnt/cdrom/${LOOP}" ]
	then
	
		bad_msg "Invalid loop location: ${LOOP}"
		bad_msg 'Please export LOOP with a valid location, or reboot and pass a proper loop=...'
		bad_msg 'kernel command line!'
	
		run_shell
	fi
}

run_shell() {
	/bin/ash
}

runUdev() {
	mount -t tmpfs -o size=100k udev /dev
	mkdir /dev/pts
	mkdir /dev/shm
	echo  > /proc/sys/kernel/hotplug 
	/sbin/udevd --daemon
	mkdir -p /dev/.udev/queue
	/sbin/udevtrigger

	good_msg 'Letting udev process events'
	loop=0
	while test -d /dev/.udev/queue; do
		sleep 1;
		test "$loop" -gt 30 && break
		loop=$(($loop + 1))
	done
	good_msg "Udev finished proccsing after $loop iterations"

	killall udevd > /dev/null 2>&1
	ln -snf /proc/self/fd /dev/fd
	ln -snf /proc/self/fd/0 /dev/stdin
	ln -snf /proc/self/fd/1 /dev/stdout
	ln -snf /proc/self/fd/2 /dev/stderr
	ln -snf /proc/kcore /dev/core
}

runmdev() {
	# busybox udev replacement
	mdev -s

	# catch udev hotplug events
	echo /sbin/mdev > /proc/sys/kernel/hotplug
}

test_success() {
	error_string=$1
	error_string="${error_string:-run command}"
	# If last command failed send error message and fall back to a shell	
	if [ "$?" != '0' ]
	then
		bad_msg 'Failed to $1; failing back to the shell...'
		run_shell
	fi
}

good_msg() {
	msg_string=$1
	msg_string="${msg_string:-...}"
	echo -e "${GOOD}>>${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
}

bad_msg() {
	msg_string=$1
	msg_string="${msg_string:-...}"
	splash 'verbose' > /dev/null &
	echo -e "${BAD}!!${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
} 

warn_msg() {
	msg_string=$1
	msg_string="${msg_string:-...}"
	echo -e "${WARN}**${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
} 

bind_mount_dev() {
	# bind-mount /dev/ so that loop devices can be found
	mount -o bind ${NEW_ROOT}/dev /dev
}

start_dev_mgr() {
	# Check udev is available...
	if [ "${KV_2_6_OR_GREATER}" -a ! "${USE_UDEV_NORMAL}" -eq '0' ]
	then
		USE_UDEV_NORMAL=1
	else
		USE_UDEV_NORMAL=0
	fi

	if [ "${USE_UDEV_NORMAL}" -eq '1' ]
	then
		cd /sys
		[ "${DO_slowusb}" ] && sleep 10
		kill_devfsd
		good_msg 'Activating mdev'
#		runUdev
		runmdev
		[ "${DO_slowusb}" ] && sleep 20
		cd /
	else
		good_msg 'Activating devfs'
		mount -t devfs devfs /dev 2>/dev/null
		devfsd /dev -np
	fi
}

bootstrapCD() {
	# Locate the cdrom device with our media on it.
	# CDROM DEVICES
	DEVICES="/dev/cdroms/* /dev/ide/cd/* /dev/sr*"
	# USB Keychain/Storage
	DEVICES="$DEVICES /dev/sd*"
	# IDE devices
	DEVICES="$DEVICES /dev/hd*"
	# USB using the USB Block Driver
	DEVICES="$DEVICES /dev/ubd* /dev/ubd/*"
	# iSeries devices
	DEVICES="$DEVICES /dev/iseries/vcd*"
	# The device was specified on the command line.  Shold we even be doing a
	# scan at this point?  I think not.
	[ -n "${CDROOT_DEV}" ] && DEVICES="$DEVICES ${CDROOT_DEV}"

	findcdmount $DEVICES
}

bootstrapKey() {
        # Locate the device with our key on it.
        # USB Keychain/Storage
        KEYDEVS="/dev/sd*"
        # CDROM DEVICES
        KEYDEVS="${KEYDEVS} /dev/cdroms/* /dev/ide/cd/* /dev/sr*"
        # IDE devices
        KEYDEVS="${KEYDEVS} /dev/hd*"
        # USB using the USB Block Driver
        KEYDEVS="${KEYDEVS} /dev/ubd* /dev/ubd/*"
        # iSeries devices
        KEYDEVS="${KEYDEVs} /dev/iseries/vcd*"

        findkeymount ${KEYDEVS}
}


cmdline_hwopts() {
	# Scan CMDLINE for any "doscsi" or "noscsi"-type arguments
	
	local FOUND
	local TMP_HWOPTS

	for x in $HWOPTS
	do
		for y in $CMDLINE
		do
			if [ "${y}" = "do${x}" ]
			then
				MY_HWOPTS="${MY_HWOPTS} $x"
			elif [ "${y}" = "no${x}" ]
			then
				MY_HWOPTS="`echo ${MY_HWOPTS} | sed -e \"s/${x}//g\" -`"
			fi
		done
	done
   
	# Shouldnt need to sort this as the following loop should figure out the
	# duplicates and strip them out
	#MY_HWOPTS=`echo ${MY_HWOPTS}|  sort`
	
	for x in ${MY_HWOPTS}
	do
		FOUND=0
		for y in ${TMP_HWOPTS}
		do
			if [ "${y}" = "${x}" ]
			then 
				FOUND=1
			fi
		done
		if [ ! "${FOUND}" = '1' ]
		then
			TMP_HWOPTS="${TMP_HWOPTS} ${x}"
		fi
	done

	MY_HWOPTS=${TMP_HWOPTS}
}

load_modules() {
	# Load modules listed in MY_HWOPTS if /lib/modules exists
	
	if [ -d '/lib/modules' ]
	then
		good_msg 'Loading modules'
		# Load appropriate kernel modules
		for modules in $MY_HWOPTS
		do
			modules_scan $modules
			eval DO_`echo $modules | sed 's/-//'`=1
		done
	else
		good_msg 'Skipping module load; no modules in the initrd!'
	fi
}

detect_sbp2_devices() {
	# http://www.linux1394.org/sbp2.php
	
	# /proc
	# /proc/scsi/sbp2/0, /proc/scsi/sbp2/1, etc.
	#
	# You may manually add/remove SBP-2 devices via the procfs with:
	# add-single-device <h> <b> <t> <l> or remove-single-device <h> <b> <t> <l>,
	# where:
	#
	# <h> = host (starting at zero for first SCSI adapter)
	# <b> = bus (normally zero)
	# <t> = target (starting at zero for first SBP-2 device)
	# <l> - lun (normally zero) 
	# e.g. To manually add/detect a new SBP-2 device
	# echo "scsi add-single-device 0 0 0 0" > /proc/scsi/scsi
	# e.g. To manually remove a SBP-2 device after it's been unplugged
	# echo "scsi remove-single-device 0 0 0 0" > /proc/scsi/scsi
	# e.g. To check to see which SBP-2/SCSI devices are currently registered
	# cat /proc/scsi/scsi 

	[ -e /proc/scsi/scsi ] && echo 'scsi add-single-device 0 0 0 0' > /proc/scsi/scsi
}

setup_keymap() {
	if [ -e $MEMORY/keyboard ]
	then
		. $MEMORY/keyboard
		loadkmap < /lib/keymaps/${XKEYBOARD}.map
	elif [ "${DO_keymap}" ]
	then
		if [ ! -e /dev/vc/0 -a ! -e /dev/tty0 ]
		then
			DEVBIND=1
			mount -o bind ${NEW_ROOT}/dev /dev
		fi
		[ ! -e /dev/tty0 ] && ln -s /dev/tty1 /dev/tty0

		chooseKeymap

		[ "${DEVBIND}" -eq '1' ] && umount /dev
		if [ -e /etc/sysconfig/keyboard -a "${USE_AUFS_NORMAL}" -eq '1' ]
		then
			cp /etc/sysconfig/keyboard $MEMORY
		elif [ -e /etc/sysconfig/keyboard -a "${CDROOT}" -eq '1' ]
		then
			mkdir -p ${NEW_ROOT}/etc/sysconfig/
			cp /etc/sysconfig/keyboard ${NEW_ROOT}/etc/sysconfig/keyboard
		fi
	fi
}

chooseKeymap() {
	good_msg "Loading keymaps"
	cat /lib/keymaps/keymapList
	read -t 10 -p '<< Load keymap (Enter for default): ' keymap
	case ${keymap} in
		1|azerty) keymap=azerty ;;
		2|be) keymap=be ;;
		3|bg) keymap=bg ;;
		4|br-a) keymap=br-a ;;
		5|br-l) keymap=br-l ;;
		6|by) keymap=by ;;
		7|cf) keymap=cf ;;
		8|croat) keymap=croat ;;
		9|cz) keymap=cz ;;
		10|de) keymap=de ;;
		11|dk) keymap=dk ;;
		12|dvorak) keymap=dvorak ;;
		13|es) keymap=es ;;
		14|et) keymap=et ;;
		15|fi) keymap=fi ;;
		16|fr) keymap=fr ;;
		17|gr) keymap=gr ;;
		18|hu) keymap=hu ;;
		19|il) keymap=il ;;
		20|is) keymap=is ;;
		21|it) keymap=it ;;
		22|jp) keymap=jp ;;
		23|la) keymap=la ;;
		24|lt) keymap=lt ;;
		25|mk) keymap=mk ;;
		26|nl) keymap=nl ;;
		27|no) keymap=no ;;
		28|pl) keymap=pl ;;
		29|pt) keymap=pt ;;
		30|ro) keymap=ro ;;
		31|ru) keymap=ru ;;
		32|se) keymap=se ;;
		33|sg) keymap=sg ;;
		34|sk-y) keymap=sk-y ;;
		35|sk-z) keymap=sk-z ;;
		36|slovene) keymap=slovene ;;
		37|trf) keymap=trf ;;
		38|trq) keymap=trq ;;
		39|ua) keymap=ua ;;
		40|uk) keymap=uk ;;
		41|us) keymap=us ;;
		42|wangbe) keymap=wangbe ;;
		43|ch*) keymap=ch\(fr\) ;;
	esac
	if [ -e /lib/keymaps/${keymap}.map ]
	then
		good_msg "Loading the ''${keymap}'' keymap"
		loadkmap < /lib/keymaps/${keymap}.map
#		xkeymap=${keymap}
#		echo ${keymap} | egrep -e "[0-9]+" >/dev/null 2>&1
#		if [ "$?" -eq '0'  ]
#		then
#			xkeymap=`tail -n 7 /lib/keymaps/keymapList | grep ${keymap} | sed -r "s/.*\s+${keymap}\s+([a-z-]+).*/\1/g" | egrep -v 1`
#		fi
		mkdir -p /etc/sysconfig
#		echo "XKEYBOARD=${xkeymap}" > /etc/sysconfig/keyboard
		echo "XKEYBOARD=\"${keymap}\"" > /etc/sysconfig/keyboard
	elif [ "$keymap" = '' ]
	then
		echo
		good_msg "Keeping default keymap"
		echo "XKEYBOARD=us" > /etc/sysconfig/keyboard
	else
		bad_msg "Sorry, but keymap ''${keymap}'' is invalid!"
		chooseKeymap
	fi
}

startVolumes() {
	#good_msg 'Checking if volumes need to be started...'

	# Here, we check for /dev/device-mapper, and if it exists, we setup a
	# a symlink, which should hopefully fix bug #142775 and bug #147015
	if [ -e /dev/device-mapper ] && [ ! -e /dev/mapper/control ]
	then
		mkdir -p /dev/mapper
		ln -sf /dev/device-mapper /dev/mapper/control
	fi
	
	if [ "${USE_MDADM}" -eq '1' ]
	then
		if [ ! -e '/etc/mdadm.conf' ]
		then
			/sbin/mdadm --examine > /etc/mdadm.conf
		fi
		/sbin/mdadm --assemble
	fi

	if [ "${USE_DMRAID_NORMAL}" -eq '1' ]
	then
		if [ -e '/sbin/dmraid' ]
		then
			good_msg "Activating Device-Mapper RAID(s)"
			if [ '${DMRAID_OPTS}' = '' ]
			then
				/sbin/dmraid -ay
			else
				/sbin/dmraid -ay ${DMRAID_OPTS}
			fi
		fi
	fi

	if [ "${USE_LVM_NORMAL}" -eq '1' ]
	then
		if [ -e '/bin/vgscan' -a -e '/bin/vgchange' ]
		then
			for dev in ${RAID_DEVICES}
			do
				setup_md_device "${dev}"
			done

			good_msg "Scanning for Volume Groups"
			/bin/vgscan --ignorelockingfailure --mknodes 2>/dev/null
			sleep 2
			good_msg "Activating Volume Groups"
			/bin/vgchange -ay --ignorelockingfailure 2>/dev/null

			# Disable EVMS since lvm is activated and they dont work together.
			if [ "${USE_EVMS_NORMAL}" -eq '1' ]
			then
				bad_msg "Disabling EVMS Support because LVM started"
				bad_msg "Do not add dolvm to the cmdline if this is not what you want"
				bad_msg "LVM and EVMS do not work well together"
				USE_EVMS_NORMAL=0
			fi
		else
			bad_msg "vgscan or vgchange not found: skipping LVM volume group activation!"
		fi
	fi

	if [ "${USE_EVMS_NORMAL}" -eq '1' ]
	then
		if [ -e '/sbin/evms_activate' ]
		then
			good_msg "Activating EVMS"
			evms_activate
		fi
	fi
}

# Open a LUKS device
# $1 LUKS device
# $2 LUKS name
openLUKS() {
	LUKS_DEVICE="$1"
	LUKS_NAME="$2"
	if [ -e /sbin/cryptsetup ]
	then
		while [ 1 ]
		do
			if [ "${LUKS_DEVICE}" = '' ]
			then
				# LUKS device could not be opened. Prompt user for device.
				bad_msg "The LUKS ${LUKS_NAME} block device is not detected."
				echo "   Please specify a ${LUKS_NAME} LUKS device to open, "q" to skip, or "shell" for a shell..."
				echo -n "LUKS ${LUKS_NAME}() :: "
				read LUKS_DEVICE
				continue
			elif [ "${LUKS_DEVICE}" = 'shell' ]
			then
				run_shell
				
				LUKS_DEVICE=''
				continue
			elif [ "${LUKS_DEVICE}" = 'q' ]
			then
				break
			else
				setup_md_device ${LUKS_DEVICE}
				if cryptsetup isLuks ${LUKS_DEVICE}
				then
					good_msg "Opening LUKS device ${LUKS_DEVICE}"
					
					cryptsetup luksOpen ${LUKS_DEVICE} ${LUKS_NAME}
					if [ ! "$?" -eq '0' ]
					then
						bad_msg "Failed open LUKS device ${LUKS_DEVICE}"
					else
						break
					fi
				else
					bad_msg "The LUKS device ${LUKS_DEVICE} does not contain a LUKS header"
				fi
			fi
			LUKS_DEVICE=''
		done
	else
		bad_msg "The initrd does not support LUKS"
	fi
}

startLUKS() {
	if [ -n "${LUKS_ROOT}" ]
	then
		openLUKS "${LUKS_ROOT}" "root" 
		if [ -n "${REAL_ROOT}" ]
		then
			# Rescan volumes
			startVolumes
		else
			REAL_ROOT="/dev/mapper/root"
		fi
	fi
	if [ -n "${LUKS_SWAP}" ]
	then
		openLUKS "${LUKS_SWAP}" "swap" 
		break
	fi
}

sdelay() {
	# Sleep a specific number of seconds if SDELAY is set otherwise only sleep
	# 1 second
	if [ -n "${SDELAY}" ]
	then
		sleep ${SDELAY}
	else
		sleep 1
	fi
}

quiet_kmsg() {
	# if QUIET is set make the kernel less chatty
	[ -n "$QUIET" ] && echo '0' > /proc/sys/kernel/printk
}

verbose_kmsg() {
	# if QUIET is set make the kernel less chatty
	[ -n "$QUIET" ] && echo '6' > /proc/sys/kernel/printk
}


cdupdate() {
	if [ "${CDROOT}" -eq '1' ]
	then
		if [ -x /${NEW_ROOT}/mnt/cdrom/cdupdate.sh ]
		then
			good_msg "Running cdupdate.sh"
			${NEW_ROOT}/mnt/cdrom/cdupdate.sh
			if [ "$?" != '0' ]
			then
				bad_msg "Executing cdupdate.sh failed!"
				run_shell
			fi
		else
			good_msg 'No cdupdate.sh script found, skipping...'
		fi
	fi
}

setup_md_device() {
	local device

	[ -z "$1" ] && device="${REAL_ROOT}" || device="$1"
	[ -z "${device}" ] && return # LiveCD

	if [ `echo ${device}|sed -e 's#\(luks:\)\?\(/dev/md\)[[:digit:]]\+#\2#'` = "/dev/md" ]
	then
		good_msg 'Detected real_root as a md device. Setting up the device node...'
		MD_NUMBER=`echo ${device}|sed -e 's#\(luks:\)\?/dev/md\([[:digit:]]\+\)#\2#'`
		if [ ! -e /dev/md${MD_NUMBER} ]
		then
			mknod /dev/md${MD_NUMBER} b 9 ${MD_NUMBER} >/dev/null 2>&1
			[ "$?" -ne 0 ] && bad_msg "Creation of /dev/md${MD_NUMBER} failed..."
		fi
		mdstart ${MDPART} /dev/md${MD_NUMBER}
	fi
}

rundebugshell() {
	if [ -n "$DEBUG" ]
	then
		good_msg 'Starting debug shell as requested by "debug" option.'
		good_msg 'Type "exit" to continue with normal bootup.'
		[ -x /bin/sh ] && /bin/sh || /bin/ash
	fi
}

# Function to create an ext2 fs on $CHANGESDEV, $CHANGESMNT mountpoint
create_changefs() {
	local size
	while [ 1 ]
	do
		read -p '<< Size of file (Enter for default 256 Mb): ' size
		if [ -z "$size" ]; then
			let size=256
		fi
		let size="$size"
		if [ $size -lt 16 ]
		then
			bad_msg "Please give a size between 16 and 512 Mb"
		elif [ $size -gt 512 ]
		then
			bad_msg "Please give a size between 16 and 512 Mb"
		else
			dd if=/dev/zero of=$CHANGESMNT/livecd.aufs bs=1M count=$size
			if [ $? = '0' ]
			then
				good_msg "Creation of livecd.aufs, $size Mb on $CHANGESDEV successful, formatting it ext2"
				mke2fs -F $CHANGESMNT/livecd.aufs
				break
			else
				rm -f $CHANGESMNT/livecd.aufs
				bad_msg "Unable to create livecd.aufs on $CHANGESDEV of $size Mb"
				bad_msg "Please give a size between 16 and 512 Mb"
				bad_msg "Also check if your disk is full or read-only ?"
			fi
		fi
	done
	return 0
}

setup_aufs() {
	if [ "${USE_AUFS_NORMAL}" -eq '1' ]
 	then
		# Directory used for rw changes in union mount filesystem
		UNION=/union
		MEMORY=/memory
		# Mountpoint for the changesdev
		CHANGESMNT=$NEW_ROOT/mnt/changesdev
		if [ -z "$UID" ]
		then
			CHANGES=$MEMORY/aufs_changes/default
		else
			CHANGES=$MEMORY/aufs_changes/$UID
		fi

		mkdir -p ${MEMORY}
		mkdir -p ${UNION}
		mkdir -p ${CHANGESMNT}
		if [ -n "${AUFS}" ]
		then
			CHANGESDEV=${AUFS}
			good_msg "mounting $CHANGESDEV to $MEMORY for aufs support"
#			mount -t auto $CHANGESDEV $MEMORY
			mount -t auto $CHANGESDEV $CHANGESMNT
			ret=$?
			if [ "${ret}" -ne 0 ]
			then
				bad_msg "mount of $CHANGESDEV failed falling back to ramdisk based aufs"
				mount -t tmpfs tmpfs $MEMORY
			fi
			# Check and attempt to create the changesfile
			if [ ! -e $CHANGESMNT/livecd.aufs ]
			then
				create_changefs
				mount -t auto $CHANGESMNT/livecd.aufs $MEMORY
			else
				local nbpass=0
				while [ 1 ]
				do
					mount -t auto $CHANGESMNT/livecd.aufs $MEMORY
					ret=$?
					if [ "${ret}" -ne 0 ]
					then
						if [ $nbpass -eq 0 ]
						then
							bad_msg "mounting of changes file failed, Running e2fsck"
							e2fsck $CHANGESMNT/livecd.aufs
							nbpass=$(($nbpass + 1))
						else
							bad_msg "mount of $CHANGESDEV failed falling back to ramdisk based aufs"
							bad_msg "your livecd.aufs might be messed up, and I couldn't fix it"
							bad_msg "moving livecd.aufs to livecd.aufs.bad"
							mv $CHANGESMNT/livecd.aufs $CHANGESMNT/livecd.aufs.bad
							bad_msg "try to fit it yourself with e2fsck later on, sorry for disturbing"
							break
						fi
					else
						if [ $nbpass -eq 1 ]
						then
							good_msg "e2fsck seemed successful. Please check your files after bootup"
						fi
						break
					fi
				done
				if [ -f ${MEMORY}/.doclean.sh ]
				then
					good_msg "finishing the permanent changes cleanup"
					. ${MEMORY}/.doclean.sh
					rm ${MEMORY}/.doclean.sh
				fi
			fi
			# mount tmpfs only in the case when changes= boot parameter was
			# empty or we were not able to mount the storage device
			if [ "${CDROOT}" -eq '1' -a ! -f ${CHANGESMNT}/livecd.aufs  ]
			then
				umount $MEMORY
				bad_msg "failed to find livecd.aufs file on $CHANGESDEV"
				bad_msg "create an ext2 livecd.aufs file on this device if you wish to use it for aufs"
				bad_msg "falling back to ramdisk based aufs for safety"
				mount -t tmpfs tmpfs $MEMORY
				XINO=$MEMORY
			else
				XINO=$MEMORY/xino
				mkdir -p $XINO
				mount -t tmpfs tmpfs $XINO
			fi
		else 
			good_msg "Mounting ramdisk to $MEMORY for aufs support..."
			mount -t tmpfs tmpfs $MEMORY
			XINO=$MEMORY
		fi 

		mkdir -p $CHANGES
		mount -t aufs -n -o nowarn_perm,udba=none,xino=$XINO/.aufs.xino,br:$CHANGES=rw aufs ${UNION}
		ret=$?
		if [ "${ret}" -ne 0 ]
		then 
			bad_msg "Can't setup union ${UNION} in directory!"
			USE_AUFS_NORMAL=0
		fi
	else
		USE_AUFS_NORMAL=0
	fi
}

tuxonice_resume() {
	[ -d /proc/suspend2 -o -d /sys/power/suspend2 -o -d /sys/power/tuxonice ] || return

	local splash_theme

	if grep "splash=" /proc/cmdline > /dev/null 2>&1; then
		splash_theme=$(cat /proc/cmdline | sed 's/.*splash=/splash=/' | sed 's/ .*//' | sed 's/.*theme://' | sed 's/,.*//')
	fi

	local tuxonice_userui_program="/sys/power/tuxonice/user_interface/program"
	local tuxonice_do_resume="/sys/power/tuxonice/do_resume"

	#
	# Backward compatibility
	#
	if [ -e /sys/power/suspend2 ]; then
		tuxonice_userui_program="/sys/power/suspend2/user_interface/program"
		tuxonice_do_resume="/sys/power/suspend2/do_resume"
	elif [ -e /proc/suspend2 ]; then
		tuxonice_userui_program="/proc/suspend2/userui_program"
		tuxonice_do_resume="/proc/suspend2/do_resume"
	fi

	modules_scan tuxonice

	if ! grep suspend_noui /proc/cmdline > /dev/null 2>&1; then
		which suspend2ui_text > /dev/null 2>&1 && which suspend2ui_text > "${tuxonice_userui_program}"
		which tuxoniceui_text > /dev/null 2>&1 && which tuxoniceui_text > "${tuxonice_userui_program}"

		if [ -n "${splash_theme}" ]; then
			ln -s /etc/splash/${splash_theme} /etc/splash/suspend2
			ln -s /etc/splash/${splash_theme} /etc/splash/tuxonice

			which suspend2ui_fbsplash > /dev/null 2>&1 && which suspend2ui_fbsplash > "${tuxonice_userui_program}"
			which tuxoniceui_fbsplash > /dev/null 2>&1 && which tuxoniceui_fbsplash > "${tuxonice_userui_program}"
		fi

		echo > "${tuxonice_do_resume}"
	fi
}
